package com.google.wallet.online.jwt.util;

import java.security.InvalidKeyException;
import java.security.SignatureException;
import java.util.List;

import net.oauth.jsontoken.JsonToken;
import net.oauth.jsontoken.JsonTokenParser;
import net.oauth.jsontoken.crypto.HmacSHA256Verifier;
import net.oauth.jsontoken.crypto.SignatureAlgorithm;
import net.oauth.jsontoken.crypto.Verifier;
import net.oauth.jsontoken.discovery.VerifierProvider;
import net.oauth.jsontoken.discovery.VerifierProviders;

import com.google.common.collect.Lists;
import com.google.wallet.online.jwt.JWTRequest;
import com.google.wallet.online.jwt.JWTResponse;

/**
 * This service converts between JWT string and Java object and vice versa
 * 
 * @author pying
 *
 */
public class WalletOnlineService {

  private String id;
  private String secret;
  
  /**
   * Constructs the Wallet Online service
   * @param id Seller Id
   * @param secret Seller secret
   */
  public WalletOnlineService(String id, String secret){
    this.id = id;
    this.secret = secret;
  }
  
  /**
   * Converts JWT object to JWT string
   * 
   * @param jwt JWT object
   * @return JWT string
   */
  public String javaToJwt(JWTRequest jwt) throws InvalidKeyException, SignatureException{
    String jwtString = null;
    jwt.setIssuer(id);
    
    //Convert
    jwtString = JWTGenerator.generate(jwt, secret);
    return jwtString;
  }
  
  /**
   * 
   * @param jwtClass
   * @param jwt
   * @return
   * @throws InstantiationException
   * @throws IllegalAccessException
   */
  public <T extends JWTResponse> T jwtToJava(Class<T> jwtClass, String jwt) throws InstantiationException, IllegalAccessException{
    T jwtObj = jwtClass.newInstance();
    
    try{
      final Verifier hmacVerifier = new HmacSHA256Verifier(secret.getBytes());
      VerifierProvider hmacLocator = new VerifierProvider() {
        
        public List<Verifier> findVerifier(String id, String key){
          return Lists.newArrayList(hmacVerifier);
        }
      };
      VerifierProviders locators = new VerifierProviders();
      locators.setVerifierProvider(SignatureAlgorithm.HS256, hmacLocator); 
      
      //Ignore Audience does not mean that the Signature is ignored
      JsonTokenParser parser = new JsonTokenParser(locators , new com.google.wallet.online.jwt.util.IgnoreAudience());
      JsonToken jt = parser.deserialize(jwt);
      
      jwtObj.jsonTokenToJwt(jt);
    } catch (InvalidKeyException e) {
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return jwtObj;
  }
}
